package org.distributed.transaction.core.interceptor;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.distributed.transaction.core.constants.TracingConstants;
import org.distributed.transaction.core.context.TracingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * SpringMVC请求的前置拦截器
 * 
 * @author chenfanglin
 *
 */
@ConditionalOnClass(HandlerInterceptor.class)
@Component
public class SpringWebInterceptor implements HandlerInterceptor, WebMvcConfigurer {

	private static final Logger log = LoggerFactory.getLogger(SpringWebInterceptor.class);

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		/**
		 * 从请求头中取出groupId放在服务跟踪上下文中
		 */
		String groupId = Optional.ofNullable(request.getHeader(TracingConstants.HEADER_KEY_GROUP_ID)).orElse("");
		String appList = Optional.ofNullable(request.getHeader(TracingConstants.HEADER_KEY_APP_MAP)).orElse("");

		Map<String, String> feilds = new HashMap<String, String>();
		feilds.put(TracingConstants.GROUP_ID, groupId);
		feilds.put(TracingConstants.APP_MAP, StringUtils.isEmpty(appList) ? appList
				: new String(Base64Utils.decodeFromString(appList), StandardCharsets.UTF_8));
		TracingContext.init(feilds);
		if (TracingContext.tracing().hasGroup()) {
			log.debug("set tracing context groupId:{}, app map:{}", groupId, appList);
		}
		return true;
	}

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(this);
	}

}
